{
 "cells": [
  {
   "cell_type": "raw",
   "id": "24071ae0",
   "metadata": {
    "vscode": {
     "languageId": "raw"
    }
   },
   "source": [
    "intent_recognition/\n",
    "├── core/\n",
    "│   ├── rule_engine.py          # 规则引擎核心\n",
    "│   ├── regex_matcher.py        # 正则匹配器\n",
    "│   ├── keyword_matcher.py      # 关键词匹配器\n",
    "│   ├── fsm_processor.py        # 有限状态机处理器\n",
    "│   └── slot_filler.py          # 槽位填充器\n",
    "├── config/\n",
    "│   ├── intents.json           # 意图配置\n",
    "│   ├── keywords.json          # 关键词库\n",
    "│   └── regex_patterns.json    # 正则模式\n",
    "├── utils/\n",
    "│   └── text_processor.py      # 文本预处理工具\n",
    "└── main.py                    # 主入口文件\n"
   ]
  },
  {
   "cell_type": "raw",
   "id": "5d6efcd4",
   "metadata": {
    "vscode": {
     "languageId": "raw"
    }
   },
   "source": [
    "整体执行流程\n",
    "\n",
    "用户输入文本\n",
    "    ↓\n",
    "文本预处理 (去除标点、转小写等)\n",
    "    ↓\n",
    "多策略并行识别\n",
    "    ├── 正则匹配器 (优先级: 高)\n",
    "    ├── 关键词匹配器 (优先级: 中)  \n",
    "    └── 状态机处理器 (优先级: 低)\n",
    "    ↓\n",
    "结果融合与决策\n",
    "    ↓\n",
    "槽位填充 (提取参数)\n",
    "    ↓\n",
    "返回最终结果\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "74937f6b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 步骤1: 输入处理\n",
    "\n",
    "# 用户输入: \"我要查订单号123456的物流状态\"\n",
    "text = \"我要查订单号123456的物流状态\"\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ea58cee1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 规则引擎核心 (rule_engine.py)\n",
    "\n",
    "class RuleBasedIntentRecognizer:\n",
    "    def __init__(self):\n",
    "        self.regex_matcher = RegexMatcher()\n",
    "        self.keyword_matcher = KeywordMatcher()\n",
    "        self.fsm_processor = FSMProcessor()\n",
    "        self.slot_filler = SlotFiller()\n",
    "        \n",
    "    def recognize(self, text):\n",
    "        \"\"\"多策略融合的意图识别\"\"\"\n",
    "        results = []\n",
    "        \n",
    "        # 1. 正则匹配 (优先级最高)\n",
    "        regex_result = self.regex_matcher.match(text)\n",
    "        if regex_result['confidence'] > 0.8:\n",
    "            results.append(regex_result)\n",
    "            \n",
    "        # 2. 关键词匹配\n",
    "        keyword_result = self.keyword_matcher.match(text)\n",
    "        results.append(keyword_result)\n",
    "        \n",
    "        # 3. 状态机处理\n",
    "        fsm_result = self.fsm_processor.process(text)\n",
    "        if fsm_result:\n",
    "            results.append(fsm_result)\n",
    "            \n",
    "        # 4. 融合决策\n",
    "        final_intent = self._merge_results(results)\n",
    "        \n",
    "        # 5. 槽位填充\n",
    "        slots = self.slot_filler.extract_slots(text, final_intent['intent'])\n",
    "        \n",
    "        return {\n",
    "            'intent': final_intent['intent'],\n",
    "            'confidence': final_intent['confidence'],\n",
    "            'slots': slots,\n",
    "            'matched_rules': final_intent['rules']\n",
    "        }\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c25bb409",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 步骤2: 正则匹配器执行\n",
    "\n",
    "# 遍历正则模式\n",
    "patterns = {\n",
    "    'query_order': [r'查.*订单.*(\\d+)', r'订单号.*?(\\d{6,})']\n",
    "}\n",
    "\n",
    "# 匹配成功: r'订单号.*?(\\d{6,})' \n",
    "# 提取到订单号: 123456\n",
    "regex_result = {\n",
    "    'intent': 'query_order',\n",
    "    'confidence': 0.9,\n",
    "    'matched_pattern': r'订单号.*?(\\d{6,})',\n",
    "    'extracted_value': ('123456',)\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d3e25e10",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 正则匹配器 (regex_matcher.py)\n",
    "\n",
    "class RegexMatcher:\n",
    "    def __init__(self):\n",
    "        self.patterns = {\n",
    "            'query_order': [\n",
    "                r'查.*订单.*(\\d+)',\n",
    "                r'订单号.*?(\\d{6,})',\n",
    "                r'我的订单.*状态'\n",
    "            ],\n",
    "            'refund': [\n",
    "                r'退.*款',\n",
    "                r'取消.*订单',\n",
    "                r'不要.*了'\n",
    "            ],\n",
    "            'issue_invoice': [\n",
    "                r'开.*发票',\n",
    "                r'要.*发票',\n",
    "                r'发票.*开'\n",
    "            ]\n",
    "        }\n",
    "    \n",
    "    def match(self, text):\n",
    "        \"\"\"正则模式匹配\"\"\"\n",
    "        for intent, patterns in self.patterns.items():\n",
    "            for pattern in patterns:\n",
    "                match = re.search(pattern, text, re.IGNORECASE)\n",
    "                if match:\n",
    "                    return {\n",
    "                        'intent': intent,\n",
    "                        'confidence': 0.9,\n",
    "                        'matched_pattern': pattern,\n",
    "                        'extracted_value': match.groups() if match.groups() else None\n",
    "                    }\n",
    "        return {'intent': 'unknown', 'confidence': 0.0}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4a398a8d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 步骤3: 关键词匹配器执行\n",
    "\n",
    "# 扫描关键词\n",
    "keywords = {\n",
    "    'query_order': {\n",
    "        'primary': ['查订单', '订单状态', '物流信息']\n",
    "    }\n",
    "}\n",
    "\n",
    "# 匹配到: \"查订单\", \"物流\"\n",
    "# 计算得分: 0.8 + 0.4 = 1.2 (截断为1.0)\n",
    "keyword_result = {\n",
    "    'intent': 'query_order', \n",
    "    'confidence': 1.0,\n",
    "    'matched_words': ['查订单', '物流']\n",
    "}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5b1e9edc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 关键词匹配器 (keyword_matcher.py)\n",
    "\n",
    "class KeywordMatcher:\n",
    "    def __init__(self):\n",
    "        self.keywords = {\n",
    "            'query_order': {\n",
    "                'primary': ['查订单', '订单状态', '物流信息'],\n",
    "                'secondary': ['快递', '发货', '到了吗'],\n",
    "                'weights': {'primary': 0.8, 'secondary': 0.4}\n",
    "            },\n",
    "            'refund': {\n",
    "                'primary': ['退钱', '退款', '退货'],\n",
    "                'secondary': ['不要', '取消', '退回'],\n",
    "                'weights': {'primary': 0.8, 'secondary': 0.4}\n",
    "            }\n",
    "        }\n",
    "    \n",
    "    def match(self, text):\n",
    "        \"\"\"关键词打分匹配\"\"\"\n",
    "        scores = {}\n",
    "        \n",
    "        for intent, config in self.keywords.items():\n",
    "            score = 0\n",
    "            matched_words = []\n",
    "            \n",
    "            # 计算主关键词得分\n",
    "            for word in config['primary']:\n",
    "                if word in text:\n",
    "                    score += config['weights']['primary']\n",
    "                    matched_words.append(word)\n",
    "            \n",
    "            # 计算次关键词得分\n",
    "            for word in config['secondary']:\n",
    "                if word in text:\n",
    "                    score += config['weights']['secondary']\n",
    "                    matched_words.append(word)\n",
    "            \n",
    "            if score > 0:\n",
    "                scores[intent] = {\n",
    "                    'score': score,\n",
    "                    'matched_words': matched_words\n",
    "                }\n",
    "        \n",
    "        # 返回得分最高的意图\n",
    "        if scores:\n",
    "            best_intent = max(scores.keys(), key=lambda x: scores[x]['score'])\n",
    "            return {\n",
    "                'intent': best_intent,\n",
    "                'confidence': min(scores[best_intent]['score'], 1.0),\n",
    "                'matched_words': scores[best_intent]['matched_words']\n",
    "            }\n",
    "        \n",
    "        return {'intent': 'unknown', 'confidence': 0.0}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eb57b3cd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 步骤4: 结果融合决策\n",
    "\n",
    "def _merge_results(self, results):\n",
    "    # 正则匹配confidence > 0.8，直接采用\n",
    "    if regex_result['confidence'] > 0.8:\n",
    "        return regex_result\n",
    "    \n",
    "    # 否则选择confidence最高的结果\n",
    "    return max(results, key=lambda x: x['confidence'])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bd3367a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 步骤5: 槽位填充\n",
    "\n",
    "# 根据意图类型提取槽位\n",
    "slots = {\n",
    "    'order_id': '123456',  # 从正则提取\n",
    "    'query_type': '物流状态'  # 从关键词推断\n",
    "}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "010687cd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 步骤6: 最终输出\n",
    "\n",
    "final_result = {\n",
    "    'intent': 'query_order',\n",
    "    'confidence': 0.9,\n",
    "    'slots': {'order_id': '123456', 'query_type': '物流状态'},\n",
    "    'matched_rules': ['regex_pattern_2', 'keyword_primary']\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5ff4842b",
   "metadata": {},
   "source": [
    "**关键设计思想**\n",
    "\n",
    "- 分层判断: 正则 → 关键词 → 状态机，优先级递减\n",
    "- 置信度机制: 每种方法都输出置信度，便于融合决策\n",
    "- 可解释性: 记录匹配的具体规则和模式\n",
    "- 兜底策略: 当所有规则都无法匹配时返回 'unknown'"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "MLOps",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
